﻿using SD.Infrastructure.EntityBase;
using SlamDunk.ValueObjects.Enums;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SlamDunk.MES.Domain.Entities.StockContext
{
    /// <summary>
    /// 出/入库记录
    /// </summary>
    public class BoundRecord : AggregateRootEntity
    {
        #region # 构造器

        #region 00.无参构造器
        /// <summary>
        /// 无参构造器
        /// </summary>
        protected BoundRecord()
        {
            //初始化导航属性
            this.RelatedBarcodes = new HashSet<BoundRecordBarcode>();
        }
        #endregion

        #region 01.创建出/入库记录构造器
        /// <summary>
        /// 创建出/入库记录构造器
        /// </summary>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="materialLotId">物料批次Id</param>
        /// <param name="directionType">出/入库方向类型</param>
        /// <param name="storageLocationType">储存位置类型</param>
        /// <param name="storageLocationId">储存位置Id</param>
        /// <param name="storageLocationName">储存位置名称</param>
        /// <param name="stockOrderClassId">库存单据类Id</param>
        /// <param name="stockOrderId">库存单据Id</param>
        /// <param name="stockOrderNo">库存单据编号</param>
        /// <param name="stockOrderDetailId">库存单据明细Id</param>
        /// <param name="quantity">数量</param>
        /// <param name="facilityId">工厂模型Id</param>
        public BoundRecord(Guid materialId, Guid? materialLotId, StockDirectionType directionType, StorageLocationType storageLocationType, string storageLocationId, string storageLocationName, Guid stockOrderClassId, Guid stockOrderId, string stockOrderNo, Guid stockOrderDetailId, decimal quantity, Guid? facilityId)
            : this()
        {
            this.MaterialId = materialId;
            this.MaterialLotId = materialLotId;
            this.DirectionType = directionType;
            this.StorageLocationType = storageLocationType;
            this.StorageLocationId = storageLocationId;
            this.StorageLocationName = storageLocationName;
            this.StockOrderClassId = stockOrderClassId;
            this.StockOrderId = stockOrderId;
            this.StockOrderNo = stockOrderNo;
            this.StockOrderDetailId = stockOrderDetailId;
            this.Quantity = quantity;
            this.FacilityId = facilityId;
        }
        #endregion

        #endregion

        #region # 属性

        #region 物料定义Id —— Guid MaterialId
        /// <summary>
        /// 物料定义Id
        /// </summary>
        public Guid MaterialId { get; private set; }
        #endregion

        #region 物料批次Id —— Guid? MaterialLotId
        /// <summary>
        /// 物料批次Id
        /// </summary>
        public Guid? MaterialLotId { get; private set; }
        #endregion

        #region 出/入库方向类型 —— StockDirectionType DirectionType
        /// <summary>
        /// 出/入库方向类型
        /// </summary>
        public StockDirectionType DirectionType { get; private set; }
        #endregion

        #region 储存位置类型 —— StorageLocationType StorageLocationType
        /// <summary>
        /// 储存位置类型
        /// </summary>
        public StorageLocationType StorageLocationType { get; private set; }
        #endregion

        #region 储存位置Id —— string StorageLocationId
        /// <summary>
        /// 储存位置Id
        /// </summary>
        public string StorageLocationId { get; private set; }
        #endregion

        #region 储存位置名称 —— string StorageLocationName
        /// <summary>
        /// 储存位置名称
        /// </summary>
        public string StorageLocationName { get; private set; }
        #endregion

        #region 库存单据类Id —— Guid StockOrderClassId
        /// <summary>
        /// 库存单据类Id
        /// </summary>
        public Guid StockOrderClassId { get; private set; }
        #endregion

        #region 库存单据Id —— Guid StockOrderId
        /// <summary>
        /// 库存单据Id
        /// </summary>
        public Guid StockOrderId { get; private set; }
        #endregion

        #region 库存单据编号 —— string StockOrderNo
        /// <summary>
        /// 库存单据编号
        /// </summary>
        public string StockOrderNo { get; private set; }
        #endregion

        #region 库存单据明细Id —— Guid StockOrderDetailId
        /// <summary>
        /// 库存单据明细Id
        /// </summary>
        public Guid StockOrderDetailId { get; private set; }
        #endregion

        #region 数量 —— decimal Quantity
        /// <summary>
        /// 数量
        /// </summary>
        public decimal Quantity { get; private set; }
        #endregion

        #region 工厂模型Id —— Guid? FacilityId
        /// <summary>
        /// 工厂模型Id
        /// </summary>
        public Guid? FacilityId { get; private set; }
        #endregion

        #region 只读属性 - 出/入库记录条码编号集 —— IEnumerable<string> RelatedBarcodeNos
        /// <summary>
        /// 只读属性 - 出/入库记录条码编号集
        /// </summary>
        public IEnumerable<string> RelatedBarcodeNos
        {
            get => this.RelatedBarcodes.Select(x => x.MaterialBarcodeNo);
        }
        #endregion

        #region 导航属性 - 出/入库记录条码集 —— ICollection<BoundRecordBarcode> RelatedBarcodes
        /// <summary>
        /// 导航属性 - 出/入库记录条码集
        /// </summary>
        public virtual ICollection<BoundRecordBarcode> RelatedBarcodes { get; private set; }
        #endregion

        #endregion

        #region # 方法

        #region 关联物料条码 —— void RelateBarcodes(IEnumerable<string> relatedBarcodeNos)
        /// <summary>
        /// 关联物料条码
        /// </summary>
        /// <param name="relatedBarcodeNos">物料条码编号集</param>
        public void RelateBarcodes(IEnumerable<string> relatedBarcodeNos)
        {
            relatedBarcodeNos = relatedBarcodeNos?.Distinct().ToArray() ?? new string[0];

            this.ClearRelatedBarcodes();
            foreach (string materialBarcodeNo in relatedBarcodeNos)
            {
                BoundRecordBarcode relatedBarcode = new BoundRecordBarcode(materialBarcodeNo);
                this.RelatedBarcodes.Add(relatedBarcode);
            }
        }
        #endregion

        #region 清空出/入库记录条码 —— void ClearRelatedBarcodes()
        /// <summary>
        /// 清空出/入库记录条码
        /// </summary>
        private void ClearRelatedBarcodes()
        {
            foreach (BoundRecordBarcode relatedBacode in this.RelatedBarcodes.ToArray())
            {
                this.RelatedBarcodes.Remove(relatedBacode);
            }
        }
        #endregion

        #endregion
    }
}
